package com.springboot.demo.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.crypto.KeyGenerator;
import javax.sql.DataSource;
import java.time.Duration;

/**
 * @author wubc683
 * @desc
 * @date 2021-07-26 9:10
 */
@Configuration
public class RedisConfig {
    @Bean
//    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL,
//                JsonTypeInfo.As.WRAPPER_ARRAY);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        // 开启事务支持
        template.setEnableTransactionSupport(true);
        return template;
    }

    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        //初始化一个RedisCacheWriter
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
        //设置CacheManager的值序列化方式为json序列化
        RedisSerializer<Object> jsonSerializer = new GenericJackson2JsonRedisSerializer();
        RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer);
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);

        //设置默认超过时期是1天
        defaultCacheConfig.entryTtl(Duration.ofDays(1));
        //初始化RedisCacheManager
        return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
    }

    /**
     * 配置事务管理器
     * @param dataSource
     * @return: org.springframework.transaction.PlatformTransactionManager
     */
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }

//    /**
//     * 配置一个CacheManager才能使用@Cacheable等注解
//     * @param template
//     * @return: CacheManager
//     */
//    @Bean
//    @Primary
//    public CacheManager cacheManager(RedisTemplate<String, Object> template) {
//
//        // 基本配置
//        RedisCacheConfiguration defaultCacheConfiguration = RedisCacheConfiguration
//                        .defaultCacheConfig()
//                        // 设置key为String
//                        .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getStringSerializer()))
//                        // 设置value 为自动转Json的Object
//                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getValueSerializer()))
//                        // 不缓存null
//                        .disableCachingNullValues()
//                        // 缓存数据保存1天
//                        .entryTtl(Duration.ofDays(1));
//
//        // redis缓存管理器
//        RedisCacheManager redisCacheManager = RedisCacheManager.RedisCacheManagerBuilder
//                        // Redis 连接工厂
//                        .fromConnectionFactory(template.getConnectionFactory())
//                        // 缓存配置
//                        .cacheDefaults(defaultCacheConfiguration)
//                        // 配置同步修改或删除 put/evict
//                        .transactionAware()
//                        .build();
//
//        return redisCacheManager;
//    }
//    //这个是自定义的一个用来测试时的 redisTemplate
//    @Bean
//    public RedisTemplate<Object, ResponseUtils> userRedisTemplate(
//            RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
//        RedisTemplate<Object, ResponseUtils> template = new RedisTemplate<>();
//        template.setConnectionFactory(redisConnectionFactory);
//        // 转换 格式
//        Jackson2JsonRedisSerializer<ResponseUtils> employeeJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<ResponseUtils>(ResponseUtils.class);
//        template.setDefaultSerializer(employeeJackson2JsonRedisSerializer);
//        return template;
//    }

}